/*
 *  lyf - Conway's Game of Life in C++
 *  Copyright (C) 2006-2008 Antoine Kalmbach
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ***/

#include <vector>
#include <iostream>
#include <algorithm>
#include "cell.h"
#include "grid.h"

namespace Life {

Grid::Grid(int xs_, int ys_) : xs(xs_), ys(ys_) 
{
    this->resize(xs, ys);
}

void Grid::resize(int xs_, int ys_)
{
    ys = ys_;
    xs = xs_;
    this->grid.resize(ys);

    for (int i = 0; i < (int) this->grid.size(); i++)
    {
        grid[i].resize(xs, false);
    }
}

void Grid::output(std::ostream &os)
{
    size_t x, y;

    for (y = 0; y < grid.size(); y++)
    {
        for (x = 0; x < grid[y].size(); x++)
        {
            os << (grid[y][x].isAlive() ? '1' : '0');
        }
        os << std::endl;
    }
}

bool Grid::isOutOfBoundaries(int x, int y)
{
    return (x >= xs || y >= ys || x < 0 || y < 0);
}

void Grid::kill(int x, int y)
{
    if (!isOutOfBoundaries(x, y)) {
        grid[y][x].kill();
    }
    else
        throw std::runtime_error("Index out of boundaries");
}

void Grid::ress(int x, int y)
{
    if (!isOutOfBoundaries(x, y)) {
        grid[y][x].resurrect();
    }
    else
        throw std::runtime_error("Index out of boundaries");
}

void Grid::growX(int x)
{
    std::vector<std::vector<Cell> >::iterator it;
    while (x--) 
    {
        for (it = grid.begin(); it != grid.end(); it++)
        {
            it->push_back(false);
        }
    }
}

void Grid::growY(int y)
{
    while (y--)
        grid.push_back(std::vector<Cell>(ys, false));
}

Cell Grid::getCell(int x, int y)
{
    if (!isOutOfBoundaries(x, y))
        return grid[y][x];
    return Cell(false);
}

void Grid::clear()
{
    std::fill(grid.begin(), grid.end(), std::vector<Cell>(ys, false));
}

void Grid::set(int x, int y, bool status)
{
    if (!isOutOfBoundaries(x, y))
        grid[y][x].set(status);
}

bool Grid::isAlive(int x, int y)
{
    if (!isOutOfBoundaries(x, y)) 
        return grid[y][x].isAlive();
    else
        return false;
}

}
